// AudioManager类 - 音频管理器（Base64版本）
class AudioManager {
    /**
     * 构造函数 - 初始化音频管理器
     * @param {Object} config - 配置对象，包含Base64音频数据
     */
    constructor(config = {}) {
        // 检查是否有全局配置，如果没有则使用传入的配置
        if (window.AUDIO_CONFIG && Object.keys(config).length === 0) {
            config = window.AUDIO_CONFIG;
        }
        
        // 合并配置
        this.config = {
            playMode: 'random',
            volume: 1.0,
            preload: false,
            maxCacheSize: 10,
            ...config
        };
        
        // 音频缓存 - 使用Map存储已创建的音频对象
        this.audioCache = new Map();
        
        // 播放状态
        this.currentIndex = 0; // 顺序播放模式的当前索引
        this.isMuted = false;  // 是否静音
        
        // 初始化音频管理器
        this.init();
    }
    
    /**
     * 初始化方法 - 根据播放模式进行不同的初始化设置
     */
    init() {
        // 根据播放模式进行不同的初始化
        switch(this.config.playMode) {
            case 'mapping':
                // 初始化人名映射模式
                this.initNameMapping();
                break;
            case 'sequence':
                // 初始化顺序播放模式
                this.initSequence();
                break;
            case 'random':
                // 随机模式无需特殊初始化
                break;
            default:
                // 如果播放模式未知，使用默认的随机模式并给出警告
                console.warn(`未知播放模式: ${this.config.playMode}, 使用随机模式`);
                this.config.playMode = 'random';
        }
        
        // 如果配置了预加载，则预加载默认音频
        if (this.config.preload) {
            this.preloadDefaultAudio();
        }
    }
    
    /**
     * 初始化人名映射模式 - 验证人名与音频Base64数据的映射关系
     */
    initNameMapping() {
        // 检查是否提供了人名映射配置
        if (!this.config.nameMapping) {
            console.warn('人名映射模式需要nameMapping配置');
            // 如果没有配置，回退到随机模式
            this.config.playMode = 'random';
            return;
        }
        
        // 验证Base64数据格式
        for (const [name, audioData] of Object.entries(this.config.nameMapping)) {
            if (!this.isValidBase64Audio(audioData)) {
                console.warn(`人名"${name}"对应的音频数据格式不正确`);
            }
        }
    }
    
    /**
     * 初始化顺序播放模式 - 设置顺序播放的起始索引
     */
    initSequence() {
        // 检查是否提供了音频序列配置
        if (!this.config.audioSequence || !Array.isArray(this.config.audioSequence)) {
            console.warn('顺序播放模式需要audioSequence配置');
            // 如果没有配置，回退到随机模式
            this.config.playMode = 'random';
            return;
        }
        
        // 验证Base64数据格式
        for (const audioData of this.config.audioSequence) {
            if (!this.isValidBase64Audio(audioData)) {
                console.warn('顺序播放列表中存在格式不正确的音频数据');
            }
        }
        
        // 重置当前索引为0，从第一个音频开始播放
        this.currentIndex = 0;
    }
    
    /**
     * 验证Base64音频数据格式
     * @param {string} audioData - Base64音频数据
     * @returns {boolean} 是否有效的Base64音频数据
     */
    isValidBase64Audio(audioData) {
        // 检查是否是Data URL格式
        if (typeof audioData !== 'string' || !audioData.startsWith('data:audio/')) {
            return false;
        }
        
        // 检查是否包含base64标识
        if (!audioData.includes('base64,')) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 预加载默认音频 - 确保默认音频可用
     */
    async preloadDefaultAudio() {
        // 如果没有配置默认音频，直接返回
        if (!this.config.defaultAudio) return;
        
        try {
            // 尝试加载默认音频
            await this.loadAudio(this.config.defaultAudio);
        } catch (error) {
            // 预加载失败，记录警告但不会阻止程序运行
            console.warn('预加载默认音频失败:', error);
        }
    }
    
    /**
     * 从Base64数据加载音频
     * @param {string} audioData - Base64音频数据
     * @returns {Promise<HTMLAudioElement>} 返回音频元素的Promise
     */
    async loadAudio(audioData) {
        // 如果音频已在缓存中，直接返回缓存的音频对象
        if (this.audioCache.has(audioData)) {
            return this.audioCache.get(audioData);
        }
        
        // 检查缓存大小，如果超过限制则移除最旧的音频（LRU策略）
        if (this.audioCache.size >= this.config.maxCacheSize) {
            // 获取第一个（最旧的）键
            const firstKey = this.audioCache.keys().next().value;
            // 从缓存中移除
            this.audioCache.delete(firstKey);
            console.log(`音频缓存已满，移除一个音频`);
        }
        
        // 创建并返回加载音频的Promise
        return new Promise((resolve, reject) => {
            // 创建新的音频元素
            const audio = new Audio();
            // 设置音频源为Base64数据
            audio.src = audioData;
            // 设置音量
            audio.volume = this.config.volume;
            
            // 设置加载超时时间（5秒）
            const timeoutId = setTimeout(() => {
                console.warn('加载Base64音频超时');
                reject(new Error('加载Base64音频超时'));
            }, 5000);
            
            // 音频可以播放时触发（已加载足够数据）
            audio.addEventListener('canplaythrough', () => {
                // 清除超时计时器
                clearTimeout(timeoutId);
                // 将音频添加到缓存
                this.audioCache.set(audioData, audio);
                // 解析Promise
                resolve(audio);
            });
            
            // 音频加载错误时触发
            audio.addEventListener('error', (e) => {
                // 清除超时计时器
                clearTimeout(timeoutId);
                // 拒绝Promise
                reject(e);
            });
            
            // 开始加载音频
            audio.load();
        });
    }
    
    /**
     * 播放音频 - 核心播放方法，根据当前播放模式选择并播放音频
     * @param {string} name - 人名（仅在映射模式下使用）
     * @returns {Promise<HTMLAudioElement|null>} 返回音频元素的Promise，失败时返回null
     */
    async play(name = null) {
        // 如果已静音，直接返回不播放
        if (this.isMuted) {
            console.log('音频已静音，跳过播放');
            return;
        }
        
        let audioData = null;
        
        // 根据播放模式选择音频数据
        try {
            switch(this.config.playMode) {
                case 'mapping':
                    // 映射模式：根据人名获取对应音频数据
                    audioData = this.getAudioByMapping(name);
                    break;
                case 'sequence':
                    // 顺序模式：按顺序获取音频数据
                    audioData = this.getAudioBySequence();
                    break;
                case 'random':
                    // 随机模式：随机获取音频数据
                    audioData = this.getAudioRandomly();
                    break;
            }
        } catch (error) {
            // 选择音频数据过程中出错
            console.error('选择音频数据时出错:', error);
        }
        
        // 如果未找到合适的音频数据，使用默认音频
        if (!audioData) {
            console.warn('未找到合适的音频数据，使用默认音频');
            audioData = this.config.defaultAudio;
        }
        
        // 如果默认音频也不存在，直接返回
        if (!audioData) {
            console.error('没有可用的音频数据');
            return null;
        }
        
        try {
            // 加载音频
            const audio = await this.loadAudio(audioData);
            // 重置播放位置到开头
            audio.currentTime = 0;
            // 播放音频
            await audio.play();
            
            // 触发播放事件，通知监听器
            if (this.eventListeners && this.eventListeners.play) {
                this.eventListeners.play.forEach(callback => {
                    try {
                        callback({
                            audioData: audioData.substring(0, 50) + '...', // 只返回部分数据用于日志
                            name,
                            mode: this.config.playMode,
                            usedDefault: audioData === this.config.defaultAudio
                        });
                    } catch (e) {
                        console.error('播放事件回调错误:', e);
                    }
                });
            }
            
            // 返回音频对象
            return audio;
        } catch (error) {
            // 播放失败，记录错误
            console.error('播放音频失败:', error);
            return null;
        }
    }
    
    /**
     * 根据人名映射获取音频数据 - 用于映射模式
     * @param {string} name - 人名
     * @returns {string|null} 返回对应的音频Base64数据，找不到时返回null
     */
    getAudioByMapping(name) {
        // 检查参数和配置
        if (!name || !this.config.nameMapping) {
            console.warn('人名映射模式需要提供name参数和nameMapping配置');
            return null;
        }
        
        // 从映射中获取音频数据
        const audioData = this.config.nameMapping[name];
        // 如果找不到对应音频，返回null（外部会处理为使用默认音频）
        return audioData || null;
    }
    
    /**
     * 根据顺序获取音频数据 - 用于顺序模式
     * @returns {string|null} 返回当前索引的音频数据，配置错误时返回null
     */
    getAudioBySequence() {
        // 检查配置
        if (!this.config.audioSequence || this.config.audioSequence.length === 0) {
            console.warn('顺序播放模式需要提供audioSequence配置');
            return null;
        }
        
        // 获取当前索引的音频数据
        const audioData = this.config.audioSequence[this.currentIndex];
        // 更新索引，循环播放
        this.currentIndex = (this.currentIndex + 1) % this.config.audioSequence.length;
        
        return audioData;
    }
    
    /**
     * 随机获取音频数据 - 用于随机模式
     * @returns {string|null} 返回随机选择的音频数据，配置错误时返回null
     */
    getAudioRandomly() {
        // 检查配置
        if (!this.config.randomPool || this.config.randomPool.length === 0) {
            console.warn('随机播放模式需要提供randomPool配置');
            return null;
        }
        
        // 生成随机索引
        const randomIndex = Math.floor(Math.random() * this.config.randomPool.length);
        // 返回随机选择的音频数据
        return this.config.randomPool[randomIndex];
    }
    
    /**
     * 停止所有音频 - 停止所有正在播放的音频
     */
    stopAll() {
        // 遍历缓存中的所有音频元素
        this.audioCache.forEach(audio => {
            // 暂停播放
            audio.pause();
            // 重置播放位置
            audio.currentTime = 0;
        });
    }
    
    /**
     * 设置音量 - 设置所有音频的音量
     * @param {number} volume - 音量值，范围0-1
     */
    setVolume(volume) {
        // 确保音量在有效范围内
        this.config.volume = Math.max(0, Math.min(1, volume));
        
        // 更新所有已缓存音频的音量
        this.audioCache.forEach(audio => {
            audio.volume = this.config.volume;
        });
    }
    
    /**
     * 切换静音状态 - 切换所有音频的静音状态
     * @returns {boolean} 返回切换后的静音状态
     */
    toggleMute() {
        // 切换静音状态
        this.isMuted = !this.isMuted;
        
        // 更新所有已缓存音频的静音状态
        this.audioCache.forEach(audio => {
            audio.muted = this.isMuted;
        });
        
        // 返回当前静音状态
        return this.isMuted;
    }
    
    /**
     * 设置播放模式 - 动态切换播放模式
     * @param {string} mode - 播放模式：'random'|'sequence'|'mapping'
     * @param {Object} config - 与新模式相关的配置
     */
    setPlayMode(mode, config = {}) {
        // 记录旧模式
        const oldMode = this.config.playMode;
        // 更新模式
        this.config.playMode = mode;
        
        // 合并新配置
        Object.assign(this.config, config);
        
        // 重新初始化
        this.init();
    }
    
    /**
     * 添加事件监听器 - 监听音频管理器的事件
     * @param {string} event - 事件名称
     * @param {Function} callback - 回调函数
     */
    addEventListener(event, callback) {
        // 初始化事件监听器对象
        if (!this.eventListeners) this.eventListeners = {};
        // 初始化特定事件的处理函数数组
        if (!this.eventListeners[event]) this.eventListeners[event] = [];
        // 添加回调函数
        this.eventListeners[event].push(callback);
    }
    
    /**
     * 移除事件监听器 - 移除特定事件的监听器
     * @param {string} event - 事件名称
     * @param {Function} callback - 要移除的回调函数
     */
    removeEventListener(event, callback) {
        // 检查事件监听器是否存在
        if (!this.eventListeners || !this.eventListeners[event]) return;
        
        // 查找回调函数的索引
        const index = this.eventListeners[event].indexOf(callback);
        // 如果找到，从数组中移除
        if (index > -1) this.eventListeners[event].splice(index, 1);
    }
    
    /**
     * 销毁资源 - 清理音频管理器的所有资源
     */
    destroy() {
        // 停止所有音频播放
        this.stopAll();
        // 清空音频缓存
        this.audioCache.clear();
        // 清空事件监听器
        this.eventListeners = {};
    }
}

// 导出AudioManager类
// 兼容CommonJS和浏览器环境
if (typeof module !== 'undefined' && module.exports) {
    // Node.js环境
    module.exports = AudioManager;
} else {
    // 浏览器环境 - 将AudioManager添加到全局window对象
    window.AudioManager = AudioManager;
}
